package com.pubinfo.passbook.common.utils;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.pubinfo.passbook.common.entity.TContractBase;
import com.pubinfo.passbook.common.entity.TRabbitmqPerson;
import com.pubinfo.passbook.common.mapper.TRabbitmqPersonMapper;
import com.pubinfo.passbook.common.model.bo.Excel;
import com.pubinfo.passbook.common.model.bo.contract.ContractImportStatus;
import com.pubinfo.passbook.common.service.contract.TContractBaseService;
import com.pubinfo.passbook.common.service.master.TSubsidiaryInfoService;
import com.pubinfo.passbook.common.service.master.TSubsidiaryPrivateKeyService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class ContractImportStatusListener extends AnalysisEventListener<ContractImportStatus> {
  
  private static final int BATCH_COUNT = 10000;
  List<ContractImportStatus> list = new ArrayList();
  
  private TContractBaseService baseService;
  
  private TRabbitmqPersonMapper tRabbitmqPersonMapper;
  
  public List<ContractImportStatus> getList() {
    return list;
  }
  
  /**
   * 假设这个是一个DAO，当然有业务逻辑这个也可以是一个service。当然如果不用存储这个对象没用。
   */
  private TSubsidiaryPrivateKeyService keyService;
  private TSubsidiaryInfoService infoService;
  private String acct;
  private HttpServletResponse response;
  
  public ContractImportStatusListener(HttpServletResponse response, String acct, TContractBaseService baseService, TRabbitmqPersonMapper tRabbitmqPersonMapper) {
    this.baseService = baseService;
    this.tRabbitmqPersonMapper = tRabbitmqPersonMapper;
    this.acct = acct;
    this.response = response;
  }
  
  public ContractImportStatusListener() {
    // 这里是demo，所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数
    //    uploadDAO = new TAutoInterfaceService();
  }
  
  /**
   * 加上存储数据库
   */
  @SneakyThrows
  @Transactional
  public void saveData() {
    Map<String, List> map = new HashMap<>();
    List<ContractImportStatus> importStatuses = new ArrayList<>();
    Integer count = 0;
    for (ContractImportStatus contractStatus : list) {
      //只保存状态
      Integer status = contractStatus.getStatus();
      String user = contractStatus.getProcessUser();
      List<TRabbitmqPerson> tRabbitmqPeople = new ArrayList<>();
      if (!map.containsKey(user)) {
        tRabbitmqPeople = tRabbitmqPersonMapper.selectAcctByNameAndPhone(user, null);
        map.put(contractStatus.getProcessUser(), tRabbitmqPeople);
      } else {
        tRabbitmqPeople = map.get(user);
      }
  
      //如果大于2条，则不保存.
      //if (tRabbitmqPeople.size() > 1) {
      //  contractStatus.setPhone("需要补充手机号");
      //  importStatuses.add(contractStatus);
      //}
      if (tRabbitmqPeople.size() == 1) {
        baseService.lambdaUpdate().set(status != null, TContractBase::getStatus, status).set(TContractBase::getModifiedBy, acct).set(TContractBase::getProcessUser, tRabbitmqPeople.get(0).getAcct()).set(TContractBase::getProcessName, user).eq(TContractBase::getContractCode, contractStatus.getContractCode()).update();
        count++;
      }
      //baseService.lambdaUpdate().set(status != null, TContractBase::getStatus, status).set(TContractBase::getModifiedBy, acct).set().eq(TContractBase::getContractCode, contractStatus.getContractCode()).update();
    }
    log.info("更新条数：" + count);
    //response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    //response.setCharacterEncoding("utf-8");
    //// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
    //String fileName = URLEncoder.encode("查询的合同", "UTF-8").replaceAll("\\+", "%20");
    //response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    //
    //List<String> includeColumnFiledNames = Arrays.asList(new String[]{"signDate", "endDate", "attachment", "contractPhone"});
    //EasyExcel.write(response.getOutputStream(), ContractImportStatus.class).excludeColumnFieldNames(includeColumnFiledNames).registerWriteHandler(new CustomSheetWriteHandler(importStatuses.size())).sheet("查询的合同").doWrite(importStatuses);
    //
  }
  
  @SneakyThrows
  @Transactional
  public void saveData2() {
    Map<String, List> map = new HashMap<>();
    List<ContractImportStatus> importStatuses = new ArrayList<>();
    Integer count = 0;
    List<String> stringList = new ArrayList<>();
    for (ContractImportStatus contractStatus : list) {
      //只保存状态
      Integer status = contractStatus.getStatus();
      String user = contractStatus.getProcessUser().trim();
      List<TRabbitmqPerson> tRabbitmqPeople = new ArrayList<>();
      String phone = contractStatus.getPhone().trim();
      if (!"需要补充手机号".equals(phone)) {
        if (!map.containsKey(phone)) {
          tRabbitmqPeople = tRabbitmqPersonMapper.selectAcctByNameAndPhone(user, phone);
          map.put(phone, tRabbitmqPeople);
        } else {
          tRabbitmqPeople = map.get(phone);
        }
        if (tRabbitmqPeople.size() == 1) {
          baseService.lambdaUpdate().set(status != null, TContractBase::getStatus, status).set(TContractBase::getModifiedBy, acct).set(TContractBase::getProcessUser, tRabbitmqPeople.get(0).getAcct()).set(TContractBase::getProcessName, user).eq(TContractBase::getContractCode, contractStatus.getContractCode()).update();
          count++;
        } else {
          stringList.add(contractStatus.getProcessUser());
        }
      }
      
      //baseService.lambdaUpdate().set(status != null, TContractBase::getStatus, status).set(TContractBase::getModifiedBy, acct).set().eq(TContractBase::getContractCode, contractStatus.getContractCode()).update();
    }
    log.info("更新条数：" + count);
    log.info("查询不到的数据：" + JSONObject.toJSONString(stringList));
    //response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
    //response.setCharacterEncoding("utf-8");
    //// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
    //String fileName = URLEncoder.encode("查询的合同", "UTF-8").replaceAll("\\+", "%20");
    //response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
    //
    //List<String> includeColumnFiledNames = Arrays.asList(new String[]{"signDate", "endDate", "attachment", "contractPhone"});
    //EasyExcel.write(response.getOutputStream(), ContractImportStatus.class).excludeColumnFieldNames(includeColumnFiledNames).registerWriteHandler(new CustomSheetWriteHandler(importStatuses.size())).sheet("查询的合同").doWrite(importStatuses);
    //
  }
  
  /**
   * 所有数据解析完成了 都会来调用
   *
   * @param context
   */
  @Override
  public void doAfterAllAnalysed(AnalysisContext context) {
    // 这里也要保存数据，确保最后遗留的数据也存储到数据库
    saveData2();
    log.info("所有数据解析完成！");
  }
  
  private Boolean checkObjIsNull(Excel interfaceImport) {
    for (Field f : interfaceImport.getClass().getDeclaredFields()) {
      f.setAccessible(true);
      try {
        if (f.get(interfaceImport) == null || "".equals(f.get(interfaceImport).toString())) { //判断字段是否为空，并且对象属性中的基本都会转为对象类型来判断
          //  throw new ServiceException("请求参数不能为空");
        }
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
      
    }
    return true;
  }
  
  /**
   * 这个每一条数据解析都会来调用
   *
   * @param data    one row value. Is is same as {@link AnalysisContext#readRowHolder()}
   * @param context
   */
  @Override
  public void invoke(ContractImportStatus data, AnalysisContext context) {
    log.info("解析到一条数据:{}", JSON.toJSONString(data));
    list.add(data);
    // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
    if (list.size() >= BATCH_COUNT) {
      saveData2();
      // 存储完成清理 list
      list.clear();
    }
  }
}
